use  std::ops::{Add, AddAssign, Mul, MulAssign};

#[derive(Debug, Clone, Copy ,PartialEq)]
pub struct Vec3{
    x: f32,
    y: f32,
    z: f32,
}

//构造函数
impl Vec3{
    #[inline(always)]
    pub fn new(x: f32, y: f32, z: f32) -> Self {
        Self { x, y, z }
    }

    /// 构建一个新的Vec3并用给定的值填充每个元素
    pub fn fill(v: f32) -> Self{
        Self{x: v, y: v, z: v}
    }
}
//拷贝构造函数
impl From<Vec3> for (f32, f32, f32){
    #[inline]
    fn from(v: Vec3) -> Self {
        (v.x, v.y, v.z)
    }
}

//使用impl Add<Vec3> for Vec3语法来表示我们正在为Vec3类型实现Add特性
impl Add<Vec3> for Vec3 {
    type Output = Vec3;
    fn add(self, v: Vec3) -> Self::Output {
        Vec3 {
            x: self.x.add(v.x),
            y: self.y.add(v.y),
            z: self.z.add(v.z),
        }
    }
}

// 将当前Vec3给定的Vec3向量相加，并将结果赋值给当前Vec3
impl AddAssign<Vec3> for Vec3 {
    fn add_assign(&mut self, v: Vec3) {
        self.x.add_assign(v.x);
        self.y.add_assign(v.y);
        self.z.add_assign(v.z);
    }
}

// 将当前Vec3给定的f32数值相加，并将结果赋值给当前Vec3
impl AddAssign<f32> for Vec3 {
    fn add_assign(&mut self, v: f32) {
        self.x.add_assign(v);
        self.y.add_assign(v);
        self.z.add_assign(v);
    }
}

/// 运算符重载实现Vec3与f32的加法运算
impl Add<f32> for Vec3 {
    type Output = Vec3;
    fn add(self, v: f32) -> Self::Output {
        Vec3 {
            x: self.x.add(v),
            y: self.y.add(v),
            z: self.z.add(v),
        }
    }
}
/// 运算符重载实现Vec3与f32的乘法运算
impl Mul<f32> for Vec3 {
    type Output = Vec3;
    fn mul(self, v: f32) -> Self::Output {
        Vec3 {
            x: self.x.mul(v),
            y: self.y.mul(v),
            z: self.z.mul(v),
        }
    }
}

/// 运算符重载实现Vec3与f32的乘法赋值运算
impl MulAssign<f32> for Vec3 {
    fn mul_assign(&mut self, v: f32) {
        self.x.mul_assign(v);
        self.y.mul_assign(v);
        self.z.mul_assign(v);
    }
}

#[cfg(test)]

mod tests {
    // 导入这个模块的所以类型
    use super::*;

    #[test]
    fn test_fill_vec3() {
        let v1 = Vec3::fill(1.0);
        let v2 = Vec3::fill(2.0);
        assert_eq!(v1 + v2, Vec3::new(3.0, 3.0, 3.0));
    }
    // Vec3乘法运算
    #[test]
    fn test_vec3_mul() {
        let mut v1 = Vec3::new(1.0, 2.0, 3.0);
        let v2 = Vec3::new(2.0, 2.0, 2.0);
        assert_eq!(v1 * v2, Vec3::new(2.0, 4.0, 6.0));
        // 赋值运算
        v1 *= v2;
        assert_eq!(v1, Vec3::new(2.0, 4.0, 6.0));
        v1 *= 2.0;
        assert_eq!(v1, Vec3::new(4.0, 8.0, 12.0));
    }

}